// 如何让一个函数使用某个值，但不获得所有权？
// & 表示引用，允许某些值不取得其所有权。 把引用作为函数参数这个行为叫做借用，且不能修改，引用默认情况下是不可变的。

pub fn refer() {

    // 不可变引用
    let s1 = String::from("hello");

    let  len = cal_length(&s1);

    println!("The length of '{}' is {}",s1,len);

    // 可变引用
    let mut s2 = String::from("hello");

    let len1 = cal_length_one(&mut s2);

    println!("The length of '{}' is {}",s2,len);

    // 可变引用在特定的作用域内，对某块数据，只能有一个可变的引用   这样做的好处是可在编译的情况下防止数据竞争
    // 以下三种行为会发生数据竞争
    // 两个或多个指针同时访问同一个数据；至少有一个指针勇敢与写入数据；没有使用任何机制来同步对数据的访问；
    // 但也可以通过创建新的作用域，来允许非同时的创建多个可变引用  可以用{}规定一个作用域
    let s3 = &mut s2;
    let s4 = &mut s2;

    println!("{},{}",s3,s4);

    // 悬空引用例子
    let r = dangle();
}

// 不可变引用
fn cal_length(s: &String) -> usize {
    s.len()
}

// 可变引用
fn cal_length_one(s: &mut String) -> usize {
    s.push_str(", world!");
    s.len()
}


// 悬空引用: 一个指针引用了内存中的某个地址，而这块内存可能已经释放并分配给其他人使用了。
fn dangle() {
    // s变量出了作用域，就已经被释放了，但是却返回了一个引用
    let s = String::from("hello");
    &s;
}

// 总结引用规则：在任何给定的时刻，只能满足下列条件之一：1.一个可变的引用 2.任意数量不可变的引用  引用必须一直有效


